namespace Boids

open System;;
open Microsoft.Xna.Framework;;
open FarseerGames.FarseerPhysics;;
open FarseerGames.FarseerPhysics.Dynamics;;


type WanderSettings = 
  struct
    val mutable wander_radius:single;
    val mutable wander_dist:single;
    val mutable change:single;
  end;;


type BoidSettings = 
  struct
    val mutable width:single;
    val mutable height:single;
    val mutable wall:single;
    val mutable wall_force:single;
    val mutable max_vel:single;
    val mutable cohesion_mult:single;
    val mutable scatter_mult:single;
    val mutable separation_mult:single;
    val mutable align_mult:single;
    val mutable range:single;
    val mutable steer_force:single;
    val mutable mass:single;
    val mutable size:Vector2;
    val mutable moment_inertia:single;
    val mutable linear_drag:single;
    val mutable rotation_drag:single;
    val mutable wander_settings:WanderSettings;
  end;;


type Boid = class
inherit Body as base;
 
  val physicsSimulator:PhysicsSimulator;
  val mutable wander_theta:single;
  val settings:BoidSettings;

    new(phys, settings:BoidSettings) as this = {
      physicsSimulator = phys;
      wander_theta = 0.f;
      settings = settings;
    } then this.init();
            
    member private b.init() =
      b.physicsSimulator.Add(b);
      b.Mass <- b.settings.mass;
      b.LinearDragCoefficient <- b.settings.linear_drag;
      b.RotationalDragCoefficient <- b.settings.rotation_drag;
      b.MomentOfInertia <- b.settings.moment_inertia;

end;;


type boid_sum = {
    pos:Vector2;
    lin_vel:Vector2;
} with
    [<OverloadID("add_sum")>]
    static member ( + ) (a, b) = 
        {pos = a.pos + b.pos;
         lin_vel = a.lin_vel + b.pos};
         
    [<OverloadID("add_boid")>]     
    static member ( + ) (a, b:Boid) = 
        {pos = a.pos + b.Position;
         lin_vel = a.lin_vel + b.LinearVelocity};         
end;;

